﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

namespace Blog.TemplateEngine
{
    class Lexer
    {
        const string BLOCK_START = "{%";
        const string BLOCK_END = "%}";
        const string VARIABLE_START = "{{";
        const string VARIABLE_END = "}}";
        const string COMMENT_START = "{#";
        const string COMMENT_END = "#}";
        static readonly string PATTERN = String.Format("({0}.*?{1}|{2}.*?{3}|{4}.*?{5})", BLOCK_START, BLOCK_END, VARIABLE_START, VARIABLE_END, COMMENT_START, COMMENT_END);
        static readonly Regex REGEX = new Regex(PATTERN, RegexOptions.Compiled);

        string mSource;

        public Lexer(string source)
        {
            mSource = source;
        }

        public List<Token> Tokenize()
        {
            var result = new List<Token>(); ;
            var is_tag = false;
            foreach (string token_src in REGEX.Split(mSource))
            {
                if (!String.IsNullOrEmpty(token_src))
                {
                    result.Add(CreateToken(token_src, is_tag));
                }
                is_tag = !is_tag;
            }

            return result;
        }

        private Token CreateToken(string token_src, bool is_tag)
        {
            if (is_tag)
            {
                if (token_src.StartsWith(BLOCK_START))
                {
                    return new Token(TokenType.Block, token_src.Substring(BLOCK_START.Length, token_src.Length - BLOCK_START.Length - BLOCK_END.Length).Trim());
                }
                else if (token_src.StartsWith(VARIABLE_START))
                {
                    return new Token(TokenType.Variable, token_src.Substring(VARIABLE_START.Length, token_src.Length - VARIABLE_START.Length - VARIABLE_END.Length).Trim());
                }
                else if (token_src.StartsWith(COMMENT_START))
                {
                    return new Token(TokenType.Comment, token_src.Substring(COMMENT_START.Length, token_src.Length - COMMENT_START.Length - COMMENT_END.Length).Trim());
                }
            }

            return new Token(TokenType.Text, token_src);
        }
    }
}
